/*
 * $HeadURL: $
 * $Id: $
 * Copyright (c) 2012 by Wodensoft System, all rights reserved.
 */
package com.wodensoft.core.script.impl;

import java.util.Map;

import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;

import com.wodensoft.core.exception.ExceptionType;
import com.wodensoft.core.exception.SystemRuntimeException;
import com.wodensoft.core.script.ScriptExecutionContext;
import com.wodensoft.core.script.ExprLangExecutor;
import com.wodensoft.core.script.ScriptExecutor;

/**
 * @author Borball
 *
 */
public class JSR223Engine implements ScriptExecutor, ExprLangExecutor {

    private JexlEngine engine;

    private int cacheSize = 200;
    private boolean silent = false;
    private boolean lenient = false;

    public JSR223Engine() {
        engine = new JexlEngine();
        engine.setCache(cacheSize);
        engine.setLenient(lenient);
        engine.setSilent(silent);
    }

    public JSR223Engine(Map<String, Object> functions) {
        this();

        engine.setFunctions(functions);
    }
    
    @Override
    public Object evaluateScript(String script, ScriptExecutionContext context) {
        try{
            return engine.createScript(script).execute(new MapContext(context.getVariableContext()));
        } catch (Exception e){
            throw new SystemRuntimeException(ExceptionType.SCRIPT, "执行[" + script + "]失败," + e.getMessage());
        }
    }

    @Override
    public Object evaluateEL(String el, ScriptExecutionContext context) {
        try{
            return engine.createExpression(el).evaluate(new MapContext(context.getVariableContext()));
        } catch (Exception e){
            throw new SystemRuntimeException(ExceptionType.SCRIPT, "执行[" + el + "]失败," + e.getMessage());
        }
    }

    /**
     * @param cacheSize the cacheSize to set
     */
    public void setCacheSize(int cacheSize) {
        engine.setCache(cacheSize);
    }

    /**
     * @param silent the silent to set
     */
    public void setSilent(boolean silent) {
        engine.setSilent(silent);
    }

    /**
     * @param lenient the lenient to set
     */
    public void setLenient(boolean lenient) {
        engine.setLenient(lenient);
    }
}
